﻿using System;
using System.Collections.Generic;

namespace Flagwind.Security.Membership
{
	/// <summary>
	/// 表示角色的实体类。
	/// </summary>
	[Serializable]
	public class Role : Flagwind.Common.ModelBase
    {
		#region 静态字段

		public static readonly string Administrators = "Administrators";
		public static readonly string Securities = "Securities";

		#endregion

		#region 成员字段

		private long _roleId;
		private DateTime _createdTime;

		#endregion

		#region 构造方法

		public Role()
		{
			_createdTime = DateTime.Now;
		}

		public Role(string name, string @namespace) : this(0, name, @namespace)
		{
		}

		public Role(long roleId, string name) : this(roleId, name, null)
		{
		}

		public Role(long roleId, string name, string @namespace)
		{
			if(string.IsNullOrWhiteSpace(name))
			{
				throw new ArgumentNullException("name");
			}

			_roleId = roleId;
			this.Name = this.FullName = name.Trim();
			this.Namespace = @namespace;
			_createdTime = DateTime.Now;
		}

        #endregion

        #region 公共属性

        public long RoleId
        {
            get
            {
                return _roleId;
            }
            set
            {
                this.SetPropertyValue(() => this.RoleId, ref _roleId, value);
            }
        }

        public string Name
        {
            get
            {
                return this.GetPropertyValue(() => this.Name);
            }
            set
            {
                //首先处理设置值为空或空字符串的情况
                if(string.IsNullOrWhiteSpace(value))
                {
                    //如果当前角色名为空，则说明是通过默认构造函数创建，因此现在不用做处理；否则抛出参数空异常
                    if(string.IsNullOrWhiteSpace(this.Name))
                        return;

                    throw new ArgumentNullException();
                }

                value = value.Trim();

                //更新属性内容
                this.SetPropertyValue(() => this.Name, value);
            }
        }

        public string FullName
        {
            get
            {
                return this.GetPropertyValue(() => this.FullName);
            }
            set
            {
                this.SetPropertyValue(() => this.FullName, value);
            }
        }

        public string Namespace
        {
            get
            {
                return this.GetPropertyValue(() => this.Namespace);
            }
            set
            {
                if(!string.IsNullOrWhiteSpace(value))
                {
                    value = value.Trim();

                    foreach(var chr in value)
                    {
                        //命名空间的字符必须是字母、数字、下划线或点号组成
                        if(!Char.IsLetterOrDigit(chr) && chr != '_' && chr != '.')
                            throw new ArgumentException("The role namespace contains invalid character.");
                    }
                }

                //更新属性内容
                this.SetPropertyValue(() => this.Namespace, string.IsNullOrWhiteSpace(value) ? null : value.Trim());
            }
        }

        public string Description
        {
            get
            {
                return this.GetPropertyValue(() => this.Description);
            }
            set
            {
                this.SetPropertyValue(() => this.Description, value);
            }
        }

        public DateTime CreatedTime
        {
            get
            {
                return _createdTime;
            }
            set
            {
                this.SetPropertyValue(() => this.CreatedTime, ref _createdTime, value);
            }
        }

        #endregion

        #region 重写方法

        public override bool Equals(object obj)
		{
			if(obj == null || obj.GetType() != this.GetType())
			{
				return false;
			}

			var other = (Role)obj;

			return _roleId == other._roleId && string.Equals(this.Namespace, other.Namespace, StringComparison.OrdinalIgnoreCase);
		}

		public override int GetHashCode()
		{
			return (this.Namespace + ":" + _roleId).ToLowerInvariant().GetHashCode();
		}

		public override string ToString()
		{
			if(string.IsNullOrWhiteSpace(this.Namespace))
			{
				return string.Format("[{0}]{1}", _roleId, this.Name);
			}
			else
			{
				return string.Format("[{0}]{1}@{2}", _roleId, this.Name, this.Namespace);
			}
		}

		#endregion

		#region 静态方法

		public static bool IsBuiltin(Role role)
		{
			if(role == null)
			{
				return false;
			}

			return IsBuiltin(role.Name);
		}

		public static bool IsBuiltin(string roleName)
		{
			return string.Equals(roleName, Role.Administrators, StringComparison.OrdinalIgnoreCase) || string.Equals(roleName, Role.Securities, StringComparison.OrdinalIgnoreCase);
		}

		#endregion
	}
}